package org.dbstar.scheduler.beans;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.dbstar.scheduler.control.JobController;
import org.dbstar.scheduler.control.exception.DaoException;
import org.dbstar.scheduler.identifier.Identifier;
import org.dbstar.scheduler.identifier.IdentifierType;
import org.dbstar.scheduler.job.JobStatus;
import org.dbstar.scheduler.utils.JobUtils;


/**
 * Job实体类
 * 
 * @author 代波
 * @since 1.0.0
 * @version 1.0.0
 * @date 2012-3-29
 */
public abstract class Job implements Serializable, Cloneable, Comparable<Job> {
	private static final long serialVersionUID = 6959194412351256470L;

	private Identifier identifier;// Job标识
	private Identifier jobConfIdentifier;// JobConf标识
	private volatile JobStatus status = JobStatus.init;// Job的状态
	private String resource;// Job所使用服务器资源
	private Map<String, String> parameters;// Job参数定义
	private boolean ready;// Job是否已经准备好执行，通常在依赖项全部满足以后

	private long submitTime = System.currentTimeMillis();
	private Long launchTime;
	private Long finishTime;

	private int retry;// 当前失败重试次数
	private int maxRetry;// 最大失败重试次数

	private String submitter;// Job提交人

	public final Identifier getIdentifier() {
		return identifier;
	}

	public final void setIdentifier(Identifier identifier) {
		if (identifier == null) {
			throw new IllegalArgumentException("Identifier must not null.");
		}
		if (identifier.getIdentifierType() != IdentifierType.job) {
			throw new IllegalArgumentException("Identifier not a Job identifier: " + identifier.getStringIdentifier());
		}
		this.identifier = identifier;
	}

	public final Identifier getJobConfIdentifier() {
		return jobConfIdentifier;
	}

	public final void setJobConfIdentifier(Identifier jobConfIdentifier) {
		if (jobConfIdentifier == null) {
			throw new IllegalArgumentException("Identifier must not null.");
		}
		if (jobConfIdentifier.getIdentifierType() != IdentifierType.conf) {
			throw new IllegalArgumentException("Identifier not a Job Configuration identifier: "
					+ jobConfIdentifier.getStringIdentifier());
		}
		this.jobConfIdentifier = jobConfIdentifier;
	}

	public final JobStatus getStatus() {
		return status;
	}

	public final void setStatus(JobStatus status) {
		if (status == null) {
			throw new IllegalArgumentException("Status must not null.");
		}
		this.status = status;
	}

	public String getResource() {
		return resource;
	}

	public void setResource(String resource) {
		this.resource = StringUtils.isBlank(resource) ? null : resource;
	}

	public final Map<String, String> getParameters() {
		return parameters;
	}

	public final void setParameters(Map<String, String> parameters) {
		this.parameters = parameters == null || parameters.isEmpty() ? null : parameters;
	}

	public final int getParameterSize() {
		return parameters == null ? 0 : parameters.size();
	}

	public boolean isReady() {
		return ready;
	}

	public void setReady(boolean ready) {
		this.ready = ready;
	}

	public final long getSubmitTime() {
		return submitTime;
	}

	public final void setSubmitTime(long submitTime) {
		this.submitTime = submitTime;
	}

	public final Long getLaunchTime() {
		return launchTime;
	}

	public final void setLaunchTime(Long launchTime) {
		this.launchTime = launchTime;
	}

	public final Long getFinishTime() {
		return finishTime;
	}

	public final void setFinishTime(Long finishTime) {
		this.finishTime = finishTime;
	}

	public final int getRetry() {
		return retry;
	}

	public final void setRetry(int retry) {
		this.retry = retry;
	}

	public final int getMaxRetry() {
		return maxRetry;
	}

	public final void setMaxRetry(int maxRetry) {
		this.maxRetry = maxRetry;
	}

	public String getSubmitter() {
		return submitter;
	}

	public void setSubmitter(String submitter) {
		this.submitter = submitter;
	}

	/**
	 * 判定任务执行结果是否为成功。
	 * 
	 * @return true-执行结果为成功;false-不成功
	 */
	public final boolean isSucceed() {
		return getResult().isSucceed();
	}

	@Override
	public Job clone() throws CloneNotSupportedException {
		Job job = (Job) super.clone();
		if (parameters != null) {
			job.parameters = new HashMap<String, String>(parameters);
		}
		return job;
	}

	@Override
	public final int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((identifier == null) ? 0 : identifier.hashCode());
		return result;
	}

	@Override
	public final boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (!Job.class.isInstance(obj))
			return false;
		Job other = (Job) obj;
		if (identifier == null) {
			if (other.identifier != null)
				return false;
		} else if (!identifier.equals(other.identifier))
			return false;
		return true;
	}

	@Override
	public int compareTo(Job o) {
		int r = status.compareTo(o.status);
		if (r == 0) {
			r = getType().compareTo(o.getType());
		}
		return r == 0 ? identifier.compareTo(o.identifier) : r;
	}

	@Override
	public String toString() {
		return getClass().getSimpleName() + " [identifier=" + identifier.getStringIdentifier() + ", status=" + status
				+ "]";
	}

	/**
	 * 获得Job的执行结果
	 * 
	 * @return Job的执行结果
	 */
	public abstract JobResult getResult();

	/**
	 * 获得Job的类型
	 * 
	 * @return Job的类型
	 */
	public abstract String getType();

	/**
	 * 获得Job的内容
	 * 
	 * @return Job的内容
	 */
	public abstract String getContent();

	/**
	 * 设置Job的内容
	 * 
	 * @param content 内容字符串
	 */
	public abstract void setContent(String content);

	/**
	 * 将Job的执行结果转换成字符串形式
	 * 
	 * @return Job的执行结果的字符串形式
	 */
	public final String getResultString() {
		return getResult().toResultString();
	}

	/**
	 * 设置Job执行结果
	 * 
	 * @param result Job执行结果的字符串形式
	 */
	public final void setResultString(String result) {
		getResult().fromResultString(result);
	}

	public boolean reExecute(boolean failedOnly, JobController jobController) throws DaoException {
		if (JobUtils.isFinished(status) || status == JobStatus.retry) {
			if (!isSucceed() || !failedOnly) {
				getResult().reExecute(this, failedOnly, jobController);
				return true;
			}
		}
		return false;
	}
}
